/*******************************************************************************
 * Copyright (c) 2014 IBM Corp.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompany this distribution.
 *
 * The Eclipse Public License is available at
 *    http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 *   http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *    Allan Stockdill-Mander - initial API and implementation and/or initial documentation
 *******************************************************************************/

#include "aliyun_iot_mqtt_net.h"

#include <stdlib.h>
#include "config.h"
#include "debug.h"
#include "aliyun_iot_platform_timer.h"
#include "aliyun_iot_platform_network.h"
#include "aliyun_iot_common_log.h"

#define DEBUG_LEVEL 2

#define VERIFY_ITEM(Result, Item, ErrMsg) \
    do { \
        if (((Result) & (Item)) != 0) { \
            WRITE_IOT_NOTICE_LOG(ErrMsg); \
        } \
    } while (0)

char expired(Timer* timer)
{
	return (char)aliyun_iot_timer_expired(&timer->end_time);
}

void countdown_ms(Timer* timer, unsigned int timeout)
{
	aliyun_iot_timer_cutdown(&timer->end_time,timeout);
}

void countdown(Timer* timer, unsigned int timeout)
{
	aliyun_iot_timer_cutdown(&timer->end_time,(timeout*1000));
}

int left_ms(Timer* timer)
{
	return aliyun_iot_timer_remain(&timer->end_time);
}

int spend_ms(Timer* timer)
{
    return aliyun_iot_timer_spend(&timer->end_time);
}

void InitTimer(Timer* timer)
{
    aliyun_iot_timer_init(&timer->end_time);
}

void StartTimer(Timer* timer)
{
    aliyun_iot_timer_start_clock(&timer->end_time);
}

int ConnectNetwork(Network* n, char* addr, char* port)
{
	int type = SOCK_STREAM_IOT;
	ALIYUN_NETWORK_SOCKADDR_IN_S address;
	memset(&address,0x0,sizeof(address));
	int rc = -1;
	INT32 family = AF_INET_IOT;
	ALIYUN_NETWORK_ADDRINFO_S *result = NULL;
	ALIYUN_NETWORK_ADDRINFO_S  hints = {0, AF_UNSPEC_IOT, SOCK_STREAM_IOT, IPPROTO_TCP_IOT, 0, NULL, NULL, NULL};

	if ((rc = aliyun_iot_network_getaddrinfo(addr, NULL, &hints, &result)) == 0)
	{
	    ALIYUN_NETWORK_ADDRINFO_S* res = result;

		/* prefer ip4 addresses */
		while (res)
		{
			if (res->ai_family == AF_INET_IOT)
			{
				result = res;
				break;
			}
			res = res->ai_next;
		}

		if (result->ai_family == AF_INET_IOT)
		{
			address.sin_port = htons(atoi(port));
			address.sin_family = family;
			address.sin_addr = ((ALIYUN_NETWORK_SOCKADDR_IN_S*)(result->ai_addr))->sin_addr;
		}
		else
		{
		    WRITE_IOT_ERROR_LOG("aliyun_iot_network_getaddrinfo error");
			rc = -1;
		}

		aliyun_iot_network_freeaddrinfo(result);
	}
	else
	{
	    WRITE_IOT_ERROR_LOG("aliyun_iot_network_getaddrinfo error! rc = %d",rc);
	}

	if (rc == 0)
	{
		n->my_socket = aliyun_iot_network_socket(family, type, IPPROTO_TCP_IOT);
		if (n->my_socket >= 0)
		{
			rc = aliyun_iot_network_connect(n->my_socket, (ALIYUN_NETWORK_SOCKADDR_IN_S*)&address, sizeof(address));
			if(0 != rc)
			{
			    WRITE_IOT_ERROR_LOG("connect error rc = %d",rc);
			}
		}
		else
		{
		    WRITE_IOT_ERROR_LOG("aliyun_iot_network_socket error,n->my_socket = %d",n->my_socket);
		}
	}

	return rc;
}

unsigned int mqtt_avRandom()
{
    return (((unsigned int)rand() << 16) + rand());
}

static int mqtt_ssl_random(void *p_rng, unsigned char *output, size_t output_len)
{
    uint32_t rnglen = output_len;
    uint8_t   rngoffset = 0;

    while (rnglen > 0)
    {
        *(output + rngoffset) = (unsigned char)mqtt_avRandom() ;
        rngoffset++;
        rnglen--;
    }
    return 0;
}


static void mqtt_ssl_debug( void *ctx, int level, const char *file, int line, const char *str )
{
    WRITE_IOT_INFO_LOG("%s,line:%d:%s\n",file,line, str);
}

int mqtt_real_confirm(int verify_result)
{
    WRITE_IOT_DEBUG_LOG("certificate verification result: 0x%02x", verify_result);
    VERIFY_ITEM(verify_result, MBEDTLS_X509_BADCERT_EXPIRED, "! fail ! server certificate has expired");
    VERIFY_ITEM(verify_result, MBEDTLS_X509_BADCERT_REVOKED, "! fail ! server certificate has been revoked");
    VERIFY_ITEM(verify_result, MBEDTLS_X509_BADCERT_CN_MISMATCH, "! fail ! CN mismatch");
    VERIFY_ITEM(verify_result, MBEDTLS_X509_BADCERT_NOT_TRUSTED, "! fail ! self-signed or not signed by a trusted CA");
    return 0;
}

static int ssl_parse_crt(mbedtls_x509_crt *crt)
{
    char buf[1024];
    mbedtls_x509_crt *local_crt = crt;
    int i = 0;
    while (local_crt)
    {
        mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", local_crt);
        {
            char str[512];
            const char *start, *cur;
            start = buf;
            for (cur = buf; *cur != '\0'; cur++)
            {
                if (*cur == '\n')
                {
                    size_t len = cur - start + 1;
                    if (len > 511)
                    {
                        len = 511;
                    }
                    memcpy(str, start, len);
                    str[len] = '\0';
                    start = cur + 1;
                    printf("%s", str);
                }
            }
        }
        WRITE_IOT_DEBUG_LOG("crt content:%zu\n", strlen(buf));
        local_crt = local_crt->next;
        i++;
    }
    return i;
}

int mqtt_ssl_client_init(mbedtls_ssl_context *ssl,
                         mbedtls_net_context *tcp_fd,
                         mbedtls_ssl_config *conf,
                         mbedtls_x509_crt *crt509_ca, const char *ca_crt, size_t ca_len,
                         mbedtls_x509_crt *crt509_cli, const char *cli_crt, size_t cli_len,
                         mbedtls_pk_context *pk_cli, const char *cli_key, size_t key_len,  const char *cli_pwd, size_t pwd_len
                        )
{
    int ret = -1;
    //verify_source_t *verify_source = &custom_config->verify_source;

    /*
     * 0. Initialize the RNG and the session data
     */
#if defined(MBEDTLS_DEBUG_C)
    mbedtls_debug_set_threshold((int)DEBUG_LEVEL);
#endif
    mbedtls_net_init( tcp_fd );
    mbedtls_ssl_init( ssl );
    mbedtls_ssl_config_init( conf );
    mbedtls_x509_crt_init(crt509_ca);

    /*verify_source->trusted_ca_crt==NULL
     * 0. Initialize certificates
     */

    WRITE_IOT_DEBUG_LOG( "  . Loading the CA root certificate ..." );
    if (NULL != ca_crt)
    {
        if (0 != (ret = mbedtls_x509_crt_parse(crt509_ca, (const unsigned char *)ca_crt, ca_len)))
        {
            WRITE_IOT_ERROR_LOG(" failed ! x509parse_crt returned -0x%04x", -ret);
            return ret;
        }
    }
    ssl_parse_crt(crt509_ca);
    WRITE_IOT_DEBUG_LOG( " ok (%d skipped)", ret );


    /* Setup Client Cert/Key */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_CERTS_C)
    mbedtls_x509_crt_init(crt509_cli);
    mbedtls_pk_init( pk_cli );
#endif
    if ( cli_crt != NULL && cli_key != NULL)
    {
#if defined(MBEDTLS_CERTS_C)
        WRITE_IOT_DEBUG_LOG("start prepare client cert .");
        ret = mbedtls_x509_crt_parse( crt509_cli, (const unsigned char *) cli_crt, cli_len );
#else
        {
            ret = 1;
            WRITE_IOT_DEBUG_LOG("MBEDTLS_CERTS_C not defined.");
        }
#endif
        if ( ret != 0 )
        {
            WRITE_IOT_ERROR_LOG( " failed!  mbedtls_x509_crt_parse returned -0x%x\n", -ret );
            return ret;
        }

#if defined(MBEDTLS_CERTS_C)
        WRITE_IOT_DEBUG_LOG("start mbedtls_pk_parse_key[%s]", cli_pwd);
        ret = mbedtls_pk_parse_key( pk_cli,(const unsigned char *) cli_key, key_len, (const unsigned char *) cli_pwd, pwd_len);
#else
        {
            ret = 1;
            WRITE_IOT_ERROR_LOG("MBEDTLS_CERTS_C not defined.");
        }
#endif

        if ( ret != 0 )
        {
            WRITE_IOT_ERROR_LOG( " failed\n  !  mbedtls_pk_parse_key returned -0x%x\n", -ret);
            return ret;
        }
    }
#endif /* MBEDTLS_X509_CRT_PARSE_C */

    return 0;
}


int mqtt_ssl_read_all(Network *n, unsigned char *buffer, int len, int timeout_ms)
{
    size_t readLen = 0;
    int ret = -1;
    WRITE_IOT_DEBUG_LOG("mqtt_ssl_read_all len=%d", len);
    WRITE_IOT_DEBUG_LOG("mqtt ssl read all timer=%d ms", timeout_ms);
    mbedtls_ssl_conf_read_timeout(&(n->tlsdataparams.conf), timeout_ms);
    while (readLen < len)
    {
        ret = mbedtls_ssl_read(&(n->tlsdataparams.ssl), (unsigned char *)(buffer + readLen), (len - readLen));
        WRITE_IOT_DEBUG_LOG("%s, mbedtls_ssl_read return:%d", __func__, ret);
        if (ret > 0)
        {
            readLen += ret;
        }
        else if (ret == 0)
        {
            WRITE_IOT_ERROR_LOG("mqtt ssl read timeout");
            return -2; //eof
        }
        else
        {
            if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
            {
                //read already complete(if call mbedtls_ssl_read again, it will return 0(eof))
                WRITE_IOT_ERROR_LOG("MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY");
                return -2;
            }

            WRITE_IOT_ERROR_LOG("mqtt recv ssl error,ret = %d",ret);
            return -1; //Connnection error
        }
    }
    WRITE_IOT_DEBUG_LOG("mqtt_ssl_read_all readlen=%zu", readLen);
    return readLen;
}

int mqtt_ssl_write_all(Network *n, unsigned char *buffer, int len, int timeout_ms)
{
    size_t writtenLen = 0;
    int ret = -1;

    WRITE_IOT_DEBUG_LOG("mqtt_ssl_write_all len=%d", len);
    WRITE_IOT_DEBUG_LOG("mqtt ssl read write timer=%d ms", timeout_ms);
    while (writtenLen < len)
    {
        ret = mbedtls_ssl_write(&(n->tlsdataparams.ssl), (unsigned char *)(buffer + writtenLen), (len - writtenLen));
        if (ret > 0)
        {
            writtenLen += ret;
            continue;
        }
        else if (ret == 0)
        {
            WRITE_IOT_ERROR_LOG("mqtt ssl write timeout");
            return -2;
        }
        else
        {
            WRITE_IOT_ERROR_LOG("mqtt ssl write fail,ret = %d",ret);
            return -1; //Connnection error
        }
    }
    WRITE_IOT_DEBUG_LOG("mqtt ssl write len=%zu", writtenLen);
    return writtenLen;
}

void mqtt_ssl_disconnect(Network *n)
{
    mbedtls_ssl_close_notify(&(n->tlsdataparams.ssl));
    mbedtls_net_free(&(n->tlsdataparams.fd));
#if defined(MBEDTLS_X509_CRT_PARSE_C)
    mbedtls_x509_crt_free( &(n->tlsdataparams.cacertl));
    if ((n->tlsdataparams.pkey).pk_info != NULL)
    {
        WRITE_IOT_DEBUG_LOG("mqtt need free client crt&key");
        mbedtls_x509_crt_free( &(n->tlsdataparams.clicert));
        mbedtls_pk_free( &(n->tlsdataparams.pkey) );
    }
#endif
    mbedtls_ssl_free( &(n->tlsdataparams.ssl));
    mbedtls_ssl_config_free(&(n->tlsdataparams.conf));
    WRITE_IOT_DEBUG_LOG( " mqtt_ssl_disconnect\n" );
}


int TLSConnectNetwork(Network *n, const char *addr, const char *port,
                      const char *ca_crt, size_t ca_crt_len,
                      const char *client_crt,	size_t client_crt_len,
                      const char *client_key,	size_t client_key_len,
                      const char *client_pwd, size_t client_pwd_len)
{
    int ret = -1;
    /*
     * 0. Init
     */
    if (0 != (ret = mqtt_ssl_client_init(&(n->tlsdataparams.ssl), &(n->tlsdataparams.fd), &(n->tlsdataparams.conf),
                                         &(n->tlsdataparams.cacertl), ca_crt, ca_crt_len,
                                         &(n->tlsdataparams.clicert), client_crt, client_crt_len,
                                         &(n->tlsdataparams.pkey), client_key, client_key_len, client_pwd, client_pwd_len)))
    {
        WRITE_IOT_ERROR_LOG( " failed ! ssl_client_init returned -0x%04x", -ret );
        return ret;
    }

    /*
     * 1. Start the connection
     */
    WRITE_IOT_DEBUG_LOG("  . Connecting to tcp/%s/%s...", addr, port);
    if (0 != (ret = mbedtls_net_connect(&(n->tlsdataparams.fd), addr, port, MBEDTLS_NET_PROTO_TCP)))
    {
        WRITE_IOT_ERROR_LOG(" failed ! net_connect returned -0x%04x", -ret);
        return ret;
    }
    WRITE_IOT_DEBUG_LOG( " ok" );

    /*
     * 2. Setup stuff
     */
    WRITE_IOT_DEBUG_LOG( "  . Setting up the SSL/TLS structure..." );
    if ( ( ret = mbedtls_ssl_config_defaults( &(n->tlsdataparams.conf),MBEDTLS_SSL_IS_CLIENT,MBEDTLS_SSL_TRANSPORT_STREAM,MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
        WRITE_IOT_ERROR_LOG( " failed! mbedtls_ssl_config_defaults returned %d", ret );
        return ret;
    }
    WRITE_IOT_DEBUG_LOG( " ok" );

    /* OPTIONAL is not optimal for security, but makes interop easier in this simplified example */
    if (ca_crt != NULL)
    {
        mbedtls_ssl_conf_authmode( &(n->tlsdataparams.conf), MBEDTLS_SSL_VERIFY_OPTIONAL );
    }
    else
    {
        mbedtls_ssl_conf_authmode( &(n->tlsdataparams.conf), MBEDTLS_SSL_VERIFY_NONE);
    }

#if defined(MBEDTLS_X509_CRT_PARSE_C)
    mbedtls_ssl_conf_ca_chain( &(n->tlsdataparams.conf), &(n->tlsdataparams.cacertl), NULL);

    if ( ( ret = mbedtls_ssl_conf_own_cert( &(n->tlsdataparams.conf), &(n->tlsdataparams.clicert), &(n->tlsdataparams.pkey) ) ) != 0 )
    {
        WRITE_IOT_ERROR_LOG( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n", ret );
        return ret;
    }
#endif
    mbedtls_ssl_conf_rng( &(n->tlsdataparams.conf), mqtt_ssl_random, NULL );
    mbedtls_ssl_conf_dbg( &(n->tlsdataparams.conf), mqtt_ssl_debug, NULL );

    if ( ( ret = mbedtls_ssl_setup(&(n->tlsdataparams.ssl), &(n->tlsdataparams.conf)) ) != 0 )
    {
        WRITE_IOT_ERROR_LOG( " failed! mbedtls_ssl_setup returned %d", ret );
        return ret;
    }
    mbedtls_ssl_set_hostname(&(n->tlsdataparams.ssl), addr);
    mbedtls_ssl_set_bio( &(n->tlsdataparams.ssl), &(n->tlsdataparams.fd), mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);

    /*
      * 4. Handshake
      */
    WRITE_IOT_DEBUG_LOG("  . Performing the SSL/TLS handshake...");

    while ((ret = mbedtls_ssl_handshake(&(n->tlsdataparams.ssl))) != 0)
    {
        if ((ret != MBEDTLS_ERR_SSL_WANT_READ) && (ret != MBEDTLS_ERR_SSL_WANT_WRITE))
        {
            WRITE_IOT_ERROR_LOG( " failed  ! mbedtls_ssl_handshake returned -0x%04x", -ret);
            return ret;
        }
    }
    WRITE_IOT_DEBUG_LOG( " ok" );
    /*
     * 5. Verify the server certificate
     */
    WRITE_IOT_DEBUG_LOG("  . Verifying peer X.509 certificate..");
    if (0 != (ret = mqtt_real_confirm(mbedtls_ssl_get_verify_result(&(n->tlsdataparams.ssl)))))
    {
        WRITE_IOT_ERROR_LOG(" failed  ! verify result not confirmed.");
        return ret;
    }
    n->my_socket = (int)((n->tlsdataparams.fd).fd);
    WRITE_IOT_DEBUG_LOG("my_socket=%d", n->my_socket);

    return 0;
}

int mqtt_connect_ssl(Network *pNetwork)
{
    if(NULL == pNetwork)
    {
        return 1;
    }

    return TLSConnectNetwork(pNetwork,pNetwork->tlsconnectparams.pHostAddress,pNetwork->tlsconnectparams.pHostPort,
                             pNetwork->tlsconnectparams.pPubKey,strlen(pNetwork->tlsconnectparams.pPubKey)+1,NULL, 0, NULL, 0, NULL, 0);
}

int mqtt_read(Network *n, unsigned char *buffer, int len, int timeout_ms)
{
    int rc = 0;
    int recvlen = 0;
    int ret = -1;
    ALIYUN_NETWORK_FD_SET_S fdset;
    ALIYUN_IOT_TIME_TYPE_S tv;

    ALIYUN_IOT_TIME_TYPE_S endTime;
    aliyun_iot_timer_cutdown(&endTime,timeout_ms);
    do
    {
        aliyun_iot_network_FD_ZERO(&fdset);
        aliyun_iot_network_FD_SET(n->my_socket, &fdset);

        INT32 lefttime = aliyun_iot_timer_remain(&endTime);
        if(lefttime <= 0)
        {
            WRITE_IOT_ERROR_LOG("mqtt read timeout");
            return -2;
        }

        aliyun_iot_timer_assignment(lefttime,&tv);

        WRITE_IOT_DEBUG_LOG("mqtt read timer=%d ms", timeout_ms);
        ret = aliyun_iot_network_select(n->my_socket + 1, &fdset, NULL, NULL, &tv);
        if (ret < 0)
        {
            INT32 err = aliyun_iot_get_errno();
            if(err == EINTR_IOT)
            {
                continue;
            }
            else
            {
                WRITE_IOT_ERROR_LOG("mqtt read(select) fail ret=%d", ret);
                return -1;
            }
        }
        else if (ret == 0)
        {
            WRITE_IOT_ERROR_LOG("mqtt read(select) timeout");
            return -2;
        }
        else if (ret == 1)
        {
            if(0 == aliyun_iot_network_FD_ISSET(n->my_socket,&fdset))
            {
                WRITE_IOT_DEBUG_LOG("another fd readable!");
                continue;
            }

            ALIYUN_IOT_TIME_TYPE_S interval;
            aliyun_iot_timer_cutdown(&interval,50);
            aliyun_iot_network_setsockopt(n->my_socket, SOL_SOCKET_IOT, SO_RCVTIMEO_IOT, (char *)&interval, sizeof(ALIYUN_IOT_TIME_TYPE_S));

            WRITE_IOT_DEBUG_LOG("mqtt read recv len = %d, recvlen = %d", len, recvlen);
            rc = aliyun_iot_network_recv(n->my_socket, buffer + recvlen, len - recvlen, 0);
            if (rc > 0)
            {
                recvlen += rc;
                WRITE_IOT_DEBUG_LOG("mqtt read ret=%d, rc = %d, recvlen = %d", ret, rc, recvlen);
            }
            else if(rc == 0)
            {
                WRITE_IOT_ERROR_LOG("The network is broken!,recvlen = %d", recvlen);
                return -3;
            }
            else
            {
                INT32 err = aliyun_iot_get_errno();
                if (err == EINTR_IOT || err == EWOULDBLOCK_IOT || err == EAGAIN_IOT)
                {
                    continue;
                }
                else
                {
                    WRITE_IOT_ERROR_LOG("mqtt read fail: ret=%d, rc = %d, recvlen = %d", ret, rc, recvlen);
                    return -3;
                }
            }
        }

    }while(recvlen < len);

    return recvlen;
}


int mqtt_write(Network *n, unsigned char *buffer, int len, int timeout_ms)
{
    int rc = 0;
    int ret = -1;
    INT32 sendlen = 0;
    ALIYUN_NETWORK_FD_SET_S fdset;
    ALIYUN_IOT_TIME_TYPE_S tv;

    INT32 timeout = timeout_ms;
    ALIYUN_IOT_TIME_TYPE_S endTime;
    aliyun_iot_timer_cutdown(&endTime,timeout);

    do
    {
        aliyun_iot_network_FD_ZERO(&fdset);
        aliyun_iot_network_FD_SET(n->my_socket, &fdset);

        INT32 lefttime = aliyun_iot_timer_remain(&endTime);
       	if(lefttime <= 0)
        {
            WRITE_IOT_ERROR_LOG("mqtt write timeout");
            return -2;
        }

        aliyun_iot_timer_assignment(lefttime,&tv);

        ret = aliyun_iot_network_select(n->my_socket + 1, NULL, &fdset, NULL, &tv);
        if (ret < 0)
        {
            INT32 err = aliyun_iot_get_errno();
            if(err == EINTR_IOT)
            {
                continue;
            }
            else
            {
                WRITE_IOT_ERROR_LOG("mqtt write fail");
                return -1;
            }
        }
        else if (ret == 0)
        {
            WRITE_IOT_ERROR_LOG("mqtt write timeout");
            return -2;
        }
        else if (ret == 1)
        {
            if(0 == aliyun_iot_network_FD_ISSET(n->my_socket,&fdset))
            {
                WRITE_IOT_DEBUG_LOG("another fd readable!");
                continue;
            }

            ALIYUN_IOT_TIME_TYPE_S interval;
            aliyun_iot_timer_cutdown(&interval,50);
            aliyun_iot_network_setsockopt(n->my_socket, SOL_SOCKET_IOT, SO_SNDTIMEO_IOT, (char *)&interval, sizeof(ALIYUN_IOT_TIME_TYPE_S));

            rc = aliyun_iot_network_send(n->my_socket, buffer, len, 0);
            if(rc > 0)
            {
                sendlen += rc;
            }
            else if(rc == 0)
            {
                WRITE_IOT_ERROR_LOG("The network is broken!");
                return -1;
            }
            else
            {
                INT32 err = aliyun_iot_get_errno();
                if(err == EINTR_IOT || err == EWOULDBLOCK_IOT || err == EAGAIN_IOT)
                {
                    continue;
                }
                else
                {
                    WRITE_IOT_ERROR_LOG("mqtt read fail: ret=%d, rc = %d, err = %d", ret, rc,err);
                    return -3;
                }
            }
        }
    }while(sendlen < len);

    return sendlen;
}


void mqtt_disconnect(Network *n)
{
    aliyun_iot_network_close(n->my_socket);
}

int mqtt_is_connected(Network *pNetwork)
{
    /* Use this to add implementation which can check for physical layer disconnect */
    return 0;
}

int mqtt_connect_tcp(Network *pNetwork)
{
    if(NULL == pNetwork)
    {
        return 1;
    }

    return ConnectNetwork(pNetwork,pNetwork->tlsconnectparams.pHostAddress, pNetwork->tlsconnectparams.pHostPort);
}

int iot_network_init(Network *pNetwork, char *addr, char *port, char *ca_crt, size_t ca_crt_len, size_t networkType)
{
    pNetwork->tlsconnectparams.pHostAddress = addr;
    pNetwork->tlsconnectparams.pHostPort = port;
    pNetwork->tlsconnectparams.pPubKey = ca_crt;

    if(0 == networkType)
    {
        pNetwork->my_socket = -1;
        pNetwork->mqttread = mqtt_read;
        pNetwork->mqttwrite= mqtt_write;
        pNetwork->disconnect = mqtt_disconnect;
        pNetwork->isConnected = mqtt_is_connected;
        pNetwork->mqttConnect = mqtt_connect_tcp;
    }
    else if(1 == networkType)
    {
        pNetwork->my_socket = -1;
        pNetwork->mqttread = mqtt_ssl_read_all;
        pNetwork->mqttwrite= mqtt_ssl_write_all;
        pNetwork->disconnect = mqtt_ssl_disconnect;
        pNetwork->isConnected = mqtt_is_connected;
        pNetwork->mqttConnect = mqtt_connect_ssl;
    }

    return 0;
}

